package RMIClient;

import RMIClient.gui.ClientGUI;

import raceReservationServer.IReservationRaceServer;
import raceReservationServer.RaceRMIDTO;
import raceReservationServer.loginGateway.ValidationException;

import util.observer.local.LocalObservable;
import util.observer.rmi.IRemoteObserver;

import java.util.Observer;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.sql.SQLException;

import java.util.List;

import authorizationRMI.InvalidPasswordException;
import authorizationRMI.InvalidUserException;
import authorizationRMI.Runner;

import authorizationRMI.IAuthorizationRMI;

public class RaceController{
	// Some data you may need
	// Feel free to add what you need
	private IReservationRaceServer server;
	private LocalObservable observable;
	private RaceRemoteObserver observer;
    private ClientGUI gui;

	// CLIENT SESSION STATE - state management field.
	private RunnerRMIDTO runner;

	/**
	 * Creates a new instance of ReservationController
	 * 
	 * @throws RemoteException
	 */
	public RaceController(String[] args) throws RemoteException {
		observable = new LocalObservable();
		if (System.getSecurityManager() == null) {
			System.setSecurityManager(new RMISecurityManager());
		}
		try {
			String URL = "//" + args[0] + ":" + args[1] + "/" + args[2];
			server= (IReservationRaceServer) Naming.lookup(URL);
		} catch (Exception e) {
			System.err.println(" Error finding the server");
			e.printStackTrace();
		}
		observer = new RaceRemoteObserver(this, server);
		gui = new ClientGUI (this);
		this.addLocalObserver(gui);
	}

	// --------------- System Events - Remote Method Invocation --------
	// TO BE COMPLETELY PROGRAMMED BY THE STUDENTS - 1st Assignment

	public RunnerRMIDTO login(String user, String pass) throws InvalidUserException, InvalidPasswordException,RemoteException{

		// add your code here
		RunnerRMIDTO aux;
		try {
			aux = server.login(user, pass);
		} catch (InvalidUserException e) {
			// TODO Auto-generated catch block
			throw e;
		} catch (InvalidPasswordException e) {
			// TODO Auto-generated catch block
			throw e;
		}
		runner=aux;
		return aux;
	}

	public List<RaceRMIDTO> getRaces() throws RemoteException{
		List<RaceRMIDTO> subjects = null;
		// add your code here
		subjects= server.getRaces();
		return subjects;
	}

	public void reservePlace(String serverName, String raceName) throws RemoteException, SQLException{
		// add your code here
		try {
			server.reservePlace(runner.getName(), serverName, raceName);
		} catch (SQLException e) {
			throw e;
		}
	}

	// -------- Remote Observer Notification ---------------
	public void updateRace(RaceRMIDTO reh){
		gui.update(observable,reh);
	}

	// ------------------ End of Remote Observer Notification --------
	public void exit() throws RemoteException {
		this.deleteLocalObserver(gui);
		observer.stop();
		System.exit(0);
	}

	// ---------------------- Local Observable ---------------------------
	public void addLocalObserver(Observer observer) {
		observable.addObserver(observer);
	}

	public void deleteLocalObserver(Observer observer) {
		observable.deleteObserver(observer);
	}

	public void notifyLocalObservers(Object arg) {
		observable.setChanged();
		observable.notifyObservers(arg);
	}
	
	/**
	 * @param args
	 *            the command line arguments
	 * @throws RemoteException
	 */
	public static void main(String[] args) throws RemoteException {
		// TODO code application logic here
	    RaceController r= new RaceController(args);
	}
}
